home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Routines to prepare objects for the scan conversion: *
- * At this stage, it is assumed all vertices normals has been evaluated, if *
- * is is required to interpolate them (i.e. Gouraud shading.) *
- * This module sort the polygons into hash table of GlblShadeInfo.ScrnYSize size, *
- * according to their lowest vertex, and update a pointer to it. *
- * *
- * Written by: Gershon Elber Ver 2.0, Mar. 1990 *
- *****************************************************************************/
-
- #include <math.h>
- #include <stdio.h>
- #include <time.h>
- #include "program.h"
- #include "genmat.h"
- #include "iritprsr.h"
-
- static void PrepareAllObjects(IPObjectStruct *PObjects);
- static void PrepareOnePolygonObject(IPObjectStruct *PObject);
- static void PrepareOnePolygon(IPPolygonStruct *PPolygon, int IsPolygon);
- static int UpdateBBoxPolygon(IPPolygonStruct *PPolygon);
- static void UpdateScanConvertData(int MinVertex, IPPolygonStruct *PPolygon);
-
- /*****************************************************************************
- * Routine to prepare NumOfObjects given in Objects from FileDescription FD *
- * according to view matrix Mat. If NumOfObjects == 0 then all the objects *
- * defined by the data sturcture are handled, and NumOfObjects is set to real *
- * number of objects exists. *
- *****************************************************************************/
- void PrepareViewData(IPObjectStruct *PObjects)
- {
- long
- SaveTime = time(NULL);
-
- fprintf(stderr, "\nPass 2, Polys = ");
-
- PrepareAllObjects(PObjects);
-
- fprintf(stderr, ", %ld seconds.", time(NULL) - SaveTime);
- #ifdef AMIGA
- fflush(stderr);
- #endif /* AMIGA */
- }
-
- /*****************************************************************************
- * Scan all objects. *
- *****************************************************************************/
- static void PrepareAllObjects(IPObjectStruct *PObjects)
- {
- while (PObjects) {
- if (IP_IS_POLY_OBJ(PObjects) && IP_IS_POLYGON_OBJ(PObjects))
- PrepareOnePolygonObject(PObjects);
- PObjects = PObjects -> Pnext;
- }
- }
-
- /*****************************************************************************
- * Routine to prepare one polygon object PObject. *
- *****************************************************************************/
- static void PrepareOnePolygonObject(IPObjectStruct *PObject)
- {
- struct IPPolygonStruct
- *PList = PObject -> U.Pl;
-
- while (PList) {
- PrepareOnePolygon(PList, IP_IS_POLYGON_OBJ(PObject));
- PList = PList -> Pnext;
- }
- }
-
- /*****************************************************************************
- * Routine to prepare one polygon PPolygon. *
- *****************************************************************************/
- static void PrepareOnePolygon(IPPolygonStruct *PPolygon, int IsPolygon)
- {
- static int
- PolyCount = 0;
- int i;
- RealType CpCoord[3];
- IPVertexStruct
- *VList = PPolygon -> PVertex;
-
- fprintf(stderr, "\b\b\b\b\b%5d", ++PolyCount);
- GlblNumOfPolys++;
-
- for (; VList != NULL; VList = VList -> Pnext) {
- /* Convert the coordinate to screen space (pres.). */
- MatMultVecby4by4(CpCoord, VList -> Coord, GlblViewMat);
- for (i = 0; i < 3; i++)
- VList -> Coord[i] = CpCoord[i];
- }
-
- if (!IsPolygon)
- return;
-
- /* Find X, Y extremum in screen space, and use the lowest vertex in Y to */
- /* initialize the scan conversion structure of the polygon: */
- i = UpdateBBoxPolygon(PPolygon);
- UpdateScanConvertData(i, PPolygon);
-
- /* Transform the polygon plane equation as well, and normalize it: */
- UpdateEqnPolygon(PPolygon, FALSE);
- }
-
- /*****************************************************************************
- * Routine to update polygon boundary box in screen space: *
- * Note this routine is called after the polygons was checked for validity - *
- * all the list of objects was found to be vertices only. *
- *****************************************************************************/
- static int UpdateBBoxPolygon(IPPolygonStruct *PPolygon)
- {
- int i,
- MinV = 0;
- RealType *Coord, Xmin, Xmax, Ymin, Ymax;
- struct IPVertexStruct
- *VList = PPolygon -> PVertex;
-
- Xmin = Xmax = VList -> Coord[0];
- Ymin = Ymax = VList -> Coord[1];
- for (VList = VList -> Pnext, i = 1;
- VList != NULL;
- VList = VList -> Pnext, i++) {
- Coord = VList -> Coord;
- if (Coord[0] > Xmax)
- Xmax = Coord[0];
- if (Coord[0] < Xmin)
- Xmin = Coord[0];
- if (Coord[1] > Ymax)
- Ymax = Coord[1];
- if (Coord[1] < Ymin) {
- Ymin = Coord[1];
- MinV = i;
- }
- }
-
- PPolygon -> BBox[0][0] = (int) Xmin;
- PPolygon -> BBox[1][0] = (int) Xmax;
- PPolygon -> BBox[0][1] = (int) Ymin;
- PPolygon -> BBox[1][1] = (int) Ymax;
-
- return MinV;
- }
-
- /*****************************************************************************
- * Routine to update polygon scan conversion information: *
- * Each polygon (Remember they must be convex), has two boundaries we cross *
- * by the scan lines if it is active. These are LeftBndry and RightBndry we *
- * update here. *
- *****************************************************************************/
- static void UpdateScanConvertData(int MinVertex, IPPolygonStruct *PPolygon)
- {
- int i;
- struct IPVertexStruct *VMinY, *VBefore, *VAfter,
- *VList = PPolygon -> PVertex;
- struct PolygonScanConvertStruct *PScan;
-
- /* Find the minimum location again: */
- if (MinVertex == 0) {
- /* Its the first vertex that has minimum Y value: */
- VMinY = VList;
- for (VBefore = VList;
- VBefore -> Pnext != NULL;
- VBefore = VBefore -> Pnext);
- VAfter = VList -> Pnext;
- }
-
- else {
- for (i = 1, VBefore = VList;
- i < MinVertex;
- i++, VBefore = VBefore -> Pnext);
- VMinY = VBefore -> Pnext;
- VAfter = VMinY -> Pnext ? VMinY -> Pnext : VList;
- }
-
- PPolygon -> PAux = IritMalloc(sizeof(struct PolygonScanConvertStruct));
- PScan = (PolygonScanConvertStruct *) PPolygon -> PAux;
-
- PScan -> Bndry1.VMinY = VMinY;
- PScan -> Bndry1.VMaxY = VBefore;
- PScan -> Bndry1.MaxEdgeY = (int) VBefore -> Coord[1];
-
- PScan -> Bndry2.VMinY = VMinY;
- PScan -> Bndry2.VMaxY = VAfter;
- PScan -> Bndry2.MaxEdgeY = (int) VAfter -> Coord[1];
- }
-